import math

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
import seaborn as sns
import cv2
import os

def plot_hottest_route(group_df, detailed_dir, save_path):
    """
    为每个MMSI模式组绘制轨迹图并保存为图片。
    group_df: DataFrame，包含某一模式组的所有MMSI。
    detailed_dir: 存储详细轨迹CSV文件的目录。
    save_path: 保存核密度估计图像的路径。
    """
    plt.style.use('dark_background')
    fig, ax = plt.subplots()
    ax.set_facecolor('black')

    # 合并所有轨迹数据进行KDE
    all_data = pd.DataFrame()

    for mmsi in group_df['MMSI']:
        detailed_file_path = os.path.join(detailed_dir, f"{mmsi}_detailed.csv")
        if os.path.exists(detailed_file_path):
            trajectory_data = pd.read_csv(detailed_file_path)
            all_data = pd.concat([all_data, trajectory_data[['LONGITUDE', 'LATITUDE']]], ignore_index=True)

    if not all_data.empty:
        sns.kdeplot(x=all_data['LONGITUDE'], y=all_data['LATITUDE'], cmap="hot", fill=True, bw_adjust=.5, ax=ax)

    ax.axis('off')
    for spine in ax.spines.values():
        spine.set_visible(False)

    plt.tight_layout(pad=0)
    fig.savefig(save_path, bbox_inches='tight', pad_inches=0, facecolor='black', dpi=300, transparent=True)
    plt.close()

def moving_average(points, window_size):
    """
    对给定的点列表进行移动平均平滑。
    points: 点列表。
    window_size: 窗口大小。
    """
    smoothed_points = []
    for i in range(len(points)):
        start = max(0, i - window_size // 2)
        end = min(len(points), i + window_size // 2 + 1)
        avg_x = int(np.mean([p[0] for p in points[start:end]]))
        avg_y = int(np.mean([p[1] for p in points[start:end]]))
        smoothed_points.append((avg_x, avg_y))
    return smoothed_points

def analyze_hottest_route(image_path, grid_size=(100, 100), window_size=5):
    """
    读取保存的图像，进行网格化分割和亮度分析。
    image_path: 图像文件的路径。
    grid_size: 网格大小。
    window_size: 移动平均平滑窗口大小。
    """
    img = cv2.imread(image_path)
    height, width, _ = img.shape
    grid_h, grid_w = grid_size
    h_step, w_step = height // grid_h, width // grid_w

    hottest_route = []

    for i in range(0, height, h_step):
        max_brightness = 0
        hottest_points = []
        for j in range(0, width, w_step):
            grid = img[i:i + h_step, j:j + w_step]
            brightness = np.mean(grid)
            if brightness > max_brightness:
                max_brightness = brightness
                hottest_points = [(j + w_step // 2, i + h_step // 2)]
            elif brightness == max_brightness:
                hottest_points.append((j + w_step // 2, i + h_step // 2))

        # 如果不是第一行，选择与上一行最亮点最近的点
        if hottest_route:
            last_point = hottest_route[-1]
            closest_point = min(hottest_points, key=lambda p: (p[0] - last_point[0]) ** 2 + (p[1] - last_point[1]) ** 2)
            hottest_route.append(closest_point)
        else:
            # 第一行选择任意一个最亮点
            hottest_route.append(hottest_points[0])

    # 对最热航线进行平滑处理
    smoothed_route = moving_average(hottest_route, window_size)

    # 绘制平滑后的最热航线
    for i in range(len(smoothed_route) - 1):
        cv2.line(img, smoothed_route[i], smoothed_route[i + 1], (0, 255, 0), thickness=15)

    # 保存结果图像
    cv2.imwrite(image_path.replace('.png', '_hottest_route.png'), img)


def speed_to_color(speed):
    """
    将速度值转换为对应的颜色。
    """
    if speed <= 9.8:
        return (0, 0, 255)  # 蓝色
    elif speed <= 10.7:
        return (0, 255, 0)  # 绿色
    else:
        return (255, 0, 0)  # 红色

def analyze_hottest_route_with_speed(image_path, data, grid_size=(100, 100)):
    """
    分析最热航线的速度动态变化带，并对整个水域进行网格划分。
    """
    img = cv2.imread(image_path)
    height, width, _ = img.shape

    lon_min, lon_max = data['LONGITUDE'].min(), data['LONGITUDE'].max()
    lat_min, lat_max = data['LATITUDE'].min(), data['LATITUDE'].max()

    # 网格划分的尺寸
    grid_h, grid_w = grid_size
    h_step, w_step = height // grid_h, width // grid_w

    # 计算每个网格的经纬度范围
    lon_step = (lon_max - lon_min) / grid_w
    lat_step = (lat_max - lat_min) / grid_h

    all_grids = []  # 存储所有网格的经纬度范围

    for i in range(grid_h):
        for j in range(grid_w):
            grid_lon_min = lon_min + j * lon_step
            grid_lon_max = grid_lon_min + lon_step
            grid_lat_min = lat_min + i * lat_step
            grid_lat_max = grid_lat_min + lat_step
            all_grids.append(((grid_lon_min, grid_lon_max), (grid_lat_min, grid_lat_max)))


    hottest_route = []  # 此处应填入最热航线的网格坐标

    for i in range(0, height, h_step):
        max_brightness = 0
        hottest_point = (0, i)
        for j in range(0, width, w_step):
            grid = img[i:i + h_step, j:j + w_step]
            brightness = np.mean(grid)
            if brightness > max_brightness:
                max_brightness = brightness
                hottest_point = (j + w_step // 2, i + h_step // 2)
        hottest_route.append(hottest_point)

    prev_point = None
    for index, (x_pixel, y_pixel) in enumerate(hottest_route):
        lon = lon_min + (lon_max - lon_min) * (x_pixel / width)
        lat = lat_min + (lat_max - lat_min) * (1 - y_pixel / height)

        grid_data = data[(data['LONGITUDE'] >= lon - lon_step / 2) & (data['LONGITUDE'] <= lon + lon_step / 2) &
                         (data['LATITUDE'] >= lat - lat_step / 2) & (data['LATITUDE'] <= lat + lat_step / 2)]

        if not grid_data.empty:
            avg_speed = grid_data['SOG'].mean()
            color = speed_to_color(avg_speed)
        else:
            # 处理无数据点的情况，使用默认颜色（如灰色）来标示这部分区域
            color = (128, 128, 128)  # 灰色

        # 如果这是列表中的第一个点，只设置prev_point，不绘制线条
        if prev_point is not None:
            cv2.line(img, prev_point, (x_pixel, y_pixel), color, thickness=2)

        prev_point = (x_pixel, y_pixel)

    cv2.imwrite(image_path.replace('.png', '_speed_analysis.png'), img)

def draw_dividing_lines(image_path, lines_params):
    """
    绘制分界线。
    image_path: 图像文件的路径。
    lines_params: 分界线参数列表，每个参数为(角度, 起点)。
    """
    img = cv2.imread(image_path)
    height, width, _ = img.shape

    for angle, start_point in lines_params:
        radians = math.radians(angle)
        end_point = (int(width), int(start_point[1] + (width - start_point[0]) * math.tan(radians)))
        cv2.line(img, start_point, end_point, (0, 255, 0), thickness=10)

    cv2.imwrite(image_path.replace('.png', '_dividing_lines.png'), img)


def analyze_hottest_route_in_zones(image_path, lines_params, grid_size=(100, 100), window_size=10):
    """
    根据分界线划分区域并分析每个区域的最热航线。
    image_path: 图像文件的路径。
    lines_params: 分界线参数列表，每个参数为(角度, 起点)。
    grid_size: 网格大小。
    window_size: 移动平均平滑窗口大小。
    """
    img = cv2.imread(image_path)
    height, width, _ = img.shape

    # 定义颜色
    colors = [(0, 0, 255), (255, 0, 0), (0, 255, 0)]  # 红色，蓝色，绿色

    # 定义区域
    zones = []
    prev_end_point = (0, height)
    for angle, start_point in lines_params:
        radians = math.radians(angle)
        end_point = (width, int(start_point[1] + (width - start_point[0]) * math.tan(radians)))
        zones.append((prev_end_point, start_point, end_point))
        prev_end_point = end_point

    zones.append((prev_end_point, (0, 0), (width, height)))  # 最后一个区域

    # 分别处理每个区域
    for zone_idx, (prev_end_point, start_point, end_point) in enumerate(zones[:3]):
        zone_img = np.zeros_like(img)
        pts = np.array([prev_end_point, start_point, end_point, (width, height), (0, height)], np.int32)
        pts = pts.reshape((-1, 1, 2))
        cv2.fillPoly(zone_img, [pts], (255, 255, 255))

        # 找到区域内的最热航线
        hottest_route = []
        h_step, w_step = height // grid_size[0], width // grid_size[1]
        for i in range(0, height, h_step):
            max_brightness = 0
            hottest_points = []
            for j in range(0, width, w_step):
                if zone_img[i, j, 0] == 255:  # 确保在区域内
                    grid = img[i:i + h_step, j:j + w_step]
                    brightness = np.mean(grid)
                    if brightness > max_brightness:
                        max_brightness = brightness
                        hottest_points = [(j + w_step // 2, i + h_step // 2)]
                    elif brightness == max_brightness:
                        hottest_points.append((j + w_step // 2, i + h_step // 2))

            if hottest_points:
                # 如果不是第一行，选择与上一行最亮点最近的点
                if hottest_route:
                    last_point = hottest_route[-1]
                    closest_point = min(hottest_points, key=lambda p: (p[0] - last_point[0]) ** 2 + (p[1] - last_point[1]) ** 2)
                    hottest_route.append(closest_point)
                else:
                    # 第一行选择任意一个最亮点
                    hottest_route.append(hottest_points[0])

        # 对最热航线进行平滑处理
        smoothed_route = moving_average(hottest_route, window_size)

        # 绘制平滑后的最热航线
        for i in range(len(smoothed_route) - 1):
            point1 = (smoothed_route[i][0], smoothed_route[i][1])
            point2 = (smoothed_route[i + 1][0], smoothed_route[i + 1][1])
            cv2.line(img, point1, point2, colors[zone_idx % len(colors)], thickness=10)

    # 保存结果图像
    cv2.imwrite(image_path.replace('.png', '_hottest_route_zones.png'), img)


def fill_to_rectangle(image_path):
    """
    将不规则图形填充为矩形，背景为黑色。
    image_path: 图像文件的路径。
    返回填充后的图像。
    """
    img = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
    height, width = img.shape[:2]

    # 找到非零区域的边界
    x, y, w, h = cv2.boundingRect(cv2.findNonZero(cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)))

    # 创建黑色背景的矩形图像
    rect_img = np.zeros((height, width, 4), dtype=np.uint8)

    # 将原始图像的非零区域复制到矩形图像上
    rect_img[y:y + h, x:x + w] = img[y:y + h, x:x + w]

    return rect_img


def cut_image_into_zones(image_path, lines_params):
    """
    根据分界线切割图像为四个子图。
    image_path: 图像文件的路径。
    lines_params: 分界线参数列表，每个参数为(角度, 起点)。
    """
    img = cv2.imread(image_path)
    height, width, _ = img.shape

    # 定义区域
    zones = []
    for angle, start_point in lines_params:
        radians = math.radians(angle)
        end_point = (width, int(start_point[1] + (width - start_point[0]) * math.tan(radians)))
        zones.append((start_point, end_point))

    # 创建子图
    zone_images = []
    for zone_idx, (start_point, end_point) in enumerate(zones):
        mask = np.zeros_like(img, dtype=np.uint8)

        if zone_idx == 0:
            pts = np.array([[start_point[0], start_point[1]], [end_point[0], end_point[1]], [width, 0], [0, 0]], np.int32)
        elif zone_idx == 1:
            prev_end_point = (width, int(zones[0][1][1] + (width - zones[0][1][0]) * math.tan(math.radians(lines_params[2][0]))))
            pts = np.array([[start_point[0], start_point[1]], [end_point[0], end_point[1]], [prev_end_point[0], prev_end_point[1]], [zones[0][0][0], zones[0][0][1]]], np.int32)
        elif zone_idx == 2:
            prev_end_point = (width, int(zones[1][1][1] + (width - zones[1][1][0]) * math.tan(math.radians(lines_params[1][0]))))
            pts = np.array([[start_point[0], start_point[1]], [end_point[0], end_point[1]], [prev_end_point[0], prev_end_point[1]], [zones[1][0][0], zones[1][0][1]]], np.int32)
        else:
            pts = np.array([[zones[2][0][0], zones[2][0][1]], [zones[2][1][0], zones[2][1][1]], [width, height], [0, height]], np.int32)

        pts = pts.reshape((-1, 1, 2))
        cv2.fillPoly(mask, [pts], (255, 255, 255))
        masked_img = cv2.bitwise_and(img, mask)
        zone_images.append(masked_img)


    # 保存子图
    for idx, zone_img in enumerate(zone_images):
        cv2.imwrite(image_path.replace('.png', f'_zone_{idx + 1}.png'), zone_img)

def analyze_hottest_route_trans(image_path, output_path, grid_size=(100, 100), window_size=15):
    """
    读取保存的图像，进行网格化分割和亮度分析。
    image_path: 图像文件的路径。
    output_path: 保存结果的路径。
    grid_size: 网格大小。
    window_size: 移动平均平滑窗口大小。
    """
    img = fill_to_rectangle(image_path)
    height, width = img.shape[:2]
    grid_h, grid_w = grid_size
    h_step, w_step = height // grid_h, width // grid_w

    hottest_route = []

    for i in range(0, height, h_step):
        max_brightness = 0
        hottest_points = []
        for j in range(0, width, w_step):
            grid = img[i:i + h_step, j:j + w_step]
            brightness = np.mean(grid)
            if brightness > max_brightness:
                max_brightness = brightness
                hottest_points = [(j + w_step // 2, i + h_step // 2)]
            elif brightness == max_brightness:
                hottest_points.append((j + w_step // 2, i + h_step // 2))

        # 如果不是第一行，选择与上一行最亮点最近的点
        if hottest_route:
            last_point = hottest_route[-1]
            closest_point = min(hottest_points, key=lambda p: (p[0] - last_point[0]) ** 2 + (p[1] - last_point[1]) ** 2)
            hottest_route.append(closest_point)
        else:
            # 第一行选择任意一个最亮点
            hottest_route.append(hottest_points[0])

    # 对最热航线进行平滑处理
    smoothed_route = moving_average(hottest_route, window_size)

    # 创建透明背景图像
    transparent_img = np.zeros((height, width, 4), dtype=np.uint8)

    # 绘制平滑后的最热航线
    for i in range(len(smoothed_route) - 1):
        cv2.line(transparent_img, smoothed_route[i], smoothed_route[i + 1], (0, 255, 0, 255), thickness=5)

    # 保存结果图像
    cv2.imwrite(output_path, transparent_img)


if __name__ == "__main__":
    grouped_dir = "./Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/MMSI_Patterns"
    detailed_dir = "./Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/Detailed_Trajectories"
    output_dir = "Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/Hottest_Plot_for_CV2"

    # 确保输出目录存在
    os.makedirs(output_dir, exist_ok=True)

    # 遍历所有MMSI模式组文件
    for group_file in os.listdir(grouped_dir):
        group_df = pd.read_csv(os.path.join(grouped_dir, group_file))
        save_path = os.path.join(output_dir, f"{group_file[:-4]}_heatmap.png")
        # plot_hottest_route(group_df, detailed_dir, save_path)
        analyze_hottest_route(save_path)

        # all_data = pd.concat([pd.read_csv(os.path.join(detailed_dir, f"{mmsi}_detailed.csv")) for mmsi in group_df['MMSI'] if os.path.exists(os.path.join(detailed_dir, f"{mmsi}_detailed.csv"))])
        # analyze_hottest_route_with_speed(save_path, all_data)

    # 分界线参数列表，每个参数为(角度, 起点)
    lines_params = [(28, (500, 0)), (30, (850, 0)), (35, (1350, 0))]

    # 绘制分界线
    # draw_dividing_lines("Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/Hottest_Plot_for_CV2/cluster_5_mmsis_heatmap.png", lines_params)

    # # # 分析划分区域内的最热航线，仅处理聚类五。因为聚类五，它其实是有多条最热航线的，不能仅仅通过单一方法绘制，因为单一方法智能绘制出一条最热航线，所以另设函数处理聚类五。
    # # analyze_hottest_route_in_zones("Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/Hottest_Plot_for_CV2/cluster_5_mmsis_heatmap_dividing_lines.png", lines_params)
    #
    # # 切割区域并保存子图像，要先按照经纬度进行大致的切割（是有一定合理性的），然后对每个切割后的区域分别进行最热航线提取
    # # cut_image_into_zones("Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/Hottest_Plot_for_CV2/cluster_5_mmsis_heatmap_dividing_lines.png", lines_params)
    #
    # # 处理每个区域的图像
    # for i in range(1, 5):
    #     image_path = f"Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/Hottest_Plot_for_CV2/zone_{i}.png"
    #     output_path =f"Data/Groups/CSJ/New_Human_Trajectories/MMSI_Cluster_Groups/Hottest_Plot_for_CV2/zone_{i}_trans.png"
    #     analyze_hottest_route_trans(image_path, output_path)